iT邦幫忙

2023 iThome 鐵人賽

DAY 3
0
SideProject30

用 Rails 打造你的電商網站系列 第 3

Day 03 用一塊一塊的積木堆積成一個網站

  • 分享至 

  • xImage
  •  

事前準備

個人檔案頁面 CRUD 及切版

元件化我們的程式碼

我們將會員系統基本功能開發完後,就先放置到一旁吧

先把畫面做出來,應該會比較直覺一點

今天我們要來做個人資料這個頁面(不過今天主題不會介紹到切版)

目前在程式開發時,元件化的架構越來越多人使用

元件化可以將複雜的程式碼拆分成一部份、一部份的小區塊,並且可以重複使用

所以我們要來介紹 View Component 這個套件啦!

安裝事宜可參考官方網站

假設個人頁面要元件化,該怎麼做呢

Step 1 尋找要做成 component 的區塊

CRUD 中,new 頁面及 edit 頁面會重複使用到 form 表單

僅有按鈕不同,或者是頁面上的說明也會不太一樣

這時候我們可以把重複的 form 表單抽出來

做成一個 component

下方是我自己切的 form 表單


<h2 class="mb-10 text-2xl">新增個人檔案</h2>

<%= form_with model: @profile, url: profiles_path do |f| %>

  <div class="flex items-center mb-4 field">
    <%= f.label :name, '姓名' , class: 'mr-4' %><br />
    <%= f.text_field :name, autocomplete: "email", class: 'rounded-md' %>
  </div>

  <div class="flex items-center mb-4 field">
    <%= f.label :address, '地址' , class: 'mr-4' %><br />
    <%= f.text_field :address, class: 'rounded-md' %>
  </div>

  <div class="flex items-center mb-4 field">
    <%= f.label :phone, '電話' , class: 'mr-4' %><br />
    <%= f.phone_field :phone, class: 'rounded-md' %>
  </div>

  <div class="flex items-center mb-4 field">
    <%= f.label :gender, '性別' , class: 'mr-4' %><br />
    <%= f.text_field :gender, class: 'rounded-md' %>
  </div>

  <div class="flex items-center mb-4 field">
    <%= f.label :birthday, '生日' , class: 'mr-4' %><br />
    <%= f.date_field :birthday, class: 'rounded-md' %>
  </div>

  <%= f.submit '送出', class: 'bg-slate-500 p-2 text-white rounded-md' %>

<% end %>

我們會將 form 表單抽出來,做成 component

Step 2 建立 component

我們可以直接下指令來做出一個 component

指令跑完會幫我們產生一個 component 的檔案及測試檔

$ rails g component ProfileForm

create  app/components/profile_form_component.rb
      invoke  test_unit
      create    test/components/profile_form_component_test.rb
      invoke  tailwindcss
      create    app/components/profile_form_component.html.erb

這時候我們來到 component 的檔案中

# components/profile_form_component.rb

class ProfileFormComponent < ViewComponent::Base
end

Step 3 設定 component 初始值

component 本身是個 class

我們可以用 initialize 的方式來幫他初始化

以這個例子來說,我要初始化的就會是 profile 這個實體變數

初始化的時候就能帶入 profile 的資料

# frozen_string_literal: true

class ProfileFormComponent < ViewComponent::Base

  def initialize(profile: )
    @profile = profile
  end
end

現在我們將 new.html.erb 中的 form 表單(要元件化的區塊)貼到 component 的 html 檔案裡

# components/profile_form_component.html.erb


<%= form_with model: @profile, url: 'profile_path' do |f| %>

  <div class="flex items-center mb-4 field">
    <%= f.label :name, '姓名' , class: 'mr-4' %><br />
    <%= f.text_field :name, autocomplete: "email", class: 'rounded-md' %>
  </div>

  <div class="flex items-center mb-4 field">
    <%= f.label :address, '地址' , class: 'mr-4' %><br />
    <%= f.text_field :address, class: 'rounded-md' %>
  </div>

  <div class="flex items-center mb-4 field">
    <%= f.label :phone, '電話' , class: 'mr-4' %><br />
    <%= f.phone_field :phone, class: 'rounded-md' %>
  </div>

  <div class="flex items-center mb-4 field">
    <%= f.label :gender, '性別' , class: 'mr-4' %><br />
    <%= f.text_field :gender, class: 'rounded-md' %>
  </div>

  <div class="flex items-center mb-4 field">
    <%= f.label :birthday, '生日' , class: 'mr-4' %><br />
    <%= f.date_field :birthday, class: 'rounded-md' %>
  </div>

  <%= f.submit '送出', class: 'bg-slate-500 p-2 text-white rounded-md' %>

<% end %>

接著我們回到 new.html.erb 將原本的 form 表單改以 component 帶入

# profiles/new.html.erb

<h2 class="mb-10 text-2xl">新增個人檔案</h2>

<%= render(ProfileFormComponent.new(profile: @profile)) %>

回到瀏覽器重新整理個人檔案的 new 頁面,這時候可能會出錯

uninitialized constant #<Class:0x00000001090f7d00>::ProfileFormComponent

一開始設定 component 時,要記得必須要重開 server

不然可能就會有問題喔

重開應該就能看到正常的畫面了

將元件帶入其他頁面

重複利用是元件化的特點之一

接下來我們必須要將剛剛的 component 帶入 edit 頁面中


<h2 class="mb-10 text-2xl">編輯個人檔案</h2>

<%= render(ProfileFormComponent.new(profile: @profile)) %>

接下來,我們可以重整瀏覽器

看到以下畫面就是成功囉

這樣我們就完成了元件化囉!

component 的其他用法

如果我們想要傳進去的是一整群資料, component 也有提供方便的用法

我們只要再 component 的 rb 檔案中加入 with_collection_parameter :profile

在 view 中使用 with_collection 方法就可以像 each 的方式,帶入一筆一筆的資料囉

<%= render(ProfileComponent.with_collection(profile: @profiles)) %>

component 做了什麼?

我們可以把 component 想像成是 Controller 跟 View

component.rb 就是 Controller

component.html.erb 就是 Ciew

component 要載入時,

component class 就會 new 出一個 component 來,

並且載入初始化設定(initialize 在此時就會執行)

最後再把這些資料帶入 view 中


上一篇
Day 02 成為會員前的一封信
下一篇
Day 04 增加圖片功能讓網站更吸睛
系列文
用 Rails 打造你的電商網站30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言